import useWorker from '@/hooks/useWorker'
import {
  evaluateState,
  FAction,
  robotState,
  sessionState,
} from '@/plugins/constants'
import emitter from '@/plugins/mitt'
import socketServer from '@/plugins/socketServer'
import {
  requestCreate,
  requestHasLeaveMessage,
  requestHistoryMessage,
  requestInitRobot,
  requestRobotChat,
  requestSelfService,
  requestTransferMenu,
  requestUnreadMessage,
  requestUpdateUnreadMessage,
  requestVisitorLeaveMessage,
  requestWebsocketBaseUrl,
  requestWorkTime,
} from '@/service'
import { useChannelStore } from '@/store/channel'
import { useChatStore } from '@/store/chat'
import { useSessionStore } from '@/store/session'
import MyWorker from '@/worker/index.ts?worker'
import { v7 as uuidv7 } from 'uuid'
import { showLoadingToast, showToast } from 'vant'
import 'vant/es/toast/style'
const { stop, start } = useWorker(MyWorker)
export const robotAction = {
  stop,
  start,
}
async function initSession(
  meetingConfig: any,
  type: 'init' | 'destroy' | 'reload' = 'init',
) {
  const session = useSessionStore()
  const { SessionIdDTO, markUserinfo, custBlackTypeInfo, visitorKeyId } =
    meetingConfig
  // 黑名单
  session.updateBlackList(custBlackTypeInfo)
  session.updateSessionId(SessionIdDTO.sessionId)
  session.updateMeetingId(SessionIdDTO.meetingId)
  const customer = {
    id: visitorKeyId,
    visitorId: markUserinfo.visitId,
    name: markUserinfo.visitName,
  }
  for (const key in customer) {
    session.updateVisitor({ key, value: customer[key] })
  }
  if (type === 'init') {
    switch (SessionIdDTO.status) {
      case sessionState.INIT:
        session.updateRobotEvaluateState(evaluateState.uncompleted)
        session.updateActionState(FAction.INIT)
        await handleSelfService(session.configId)
        await handleInitState(type)
        break
      case sessionState.ROBOT:
        await handleInitState(type)
        session.updateActionState(FAction.ROBOT)
        stop()
        start()
        break
      case sessionState.REQAGENT:
        session.updateActionState(FAction.REQAGENT)
        // 排队中
        await handlePreAgent('retry')
        break
      case sessionState.AGENT:
        session.updateActionState(FAction.AGENT)
        await handleAgent('retry')
        // 客服对话
        break
    }
  } else {
    switch (SessionIdDTO.status) {
      case sessionState.INIT:
        session.updateRobotEvaluateState(evaluateState.uncompleted)
        session.updateActionState(FAction.INIT)
        await handleInitState(type)
        break
      case sessionState.ROBOT:
        await handleInitState(type)
        session.updateActionState(FAction.ROBOT)
        stop()
        start()
        break
      case sessionState.REQAGENT:
        session.updateActionState(FAction.REQAGENT)
        // 排队中
        await handlePreAgent('retry')
        break
      case sessionState.AGENT:
        session.updateActionState(FAction.AGENT)
        await handleAgent('retry')
        break
    }
  }
}
// 加载欢迎语
async function loadWelcome(type) {
  const channel = useChannelStore()
  const chat = useChatStore()
  if (channel.SystemInfo.openRobot) {
    // 加载机器人
    await loadRobot(type)
  } else {
    // 未开启机器人则展示渠道欢迎语
    chat.updateMessages({
      content: channel.SystemInfo.channelWelcome,
      role: 'system',
      type: 'text',
      id: uuidv7(),
    })
  }
}
// 加载机器人
async function loadRobot(type: 'init' | 'destroy' | 'reload' = 'init') {
  // 初始化加载和销毁后重新加载机器人
  const channel = useChannelStore()
  const session = useSessionStore()
  const chat = useChatStore()
  const params = {
    configId: session.configId,
    meetingId: session.meetingId,
    sessionId: session.sessionId,
    robotChannelId: channel.SystemInfo.robotChannelId,
    tenantId: channel.SystemInfo.tenantId,
    status: channel.SystemInfo.robotState,
    userId: session.visitorId,
  }
  const result: any = await requestInitRobot(params)

  if (result.code === 0) {
    session.updateActionState(FAction.ROBOT)
    session.updateRobotState(robotState.OPEN)
    if (type === 'init') {
      // 初始化加载机器人展示欢迎语
      chat.updateMessages({
        content: result.data.title,
        role: 'robot',
        type: 'text',
        id: uuidv7(),
      })
    }
    stop()
    start()
  }
}
// init状态业务处理
async function handleInitState(type) {
  // 加载欢迎语
  await loadWelcome(type)
}
// 自助服务
async function handleSelfService(configId) {
  const result: any = await requestSelfService({ configId })
  const chat = useChatStore()
  const message = [
    {
      role: 'system',
      type: 'selfService',
      content: result.data,
      id: uuidv7(),
    },
    {
      role: 'system',
      type: 'guess',
      id: uuidv7(),
    },
  ]
  message.forEach((item) => chat.updateMessages(item))
}
// 机器人发送消息
async function sendRobotMessage(value: any, callback: () => void) {
  const session = useSessionStore()
  return new Promise(async (resolve) => {
    // 判断机器人状态 销毁状态重新创建机器人 开启状态则发送消息
    switch (session.FAction) {
      case FAction.TIMEOUT:
      case FAction.DESTROY:
        // 排队超时或销毁
        await createMeeting('reload')
        requestRobotMessage(resolve, value, callback)
        break
      default:
        requestRobotMessage(resolve, value, callback)
        break
    }
  })
}
// 会话创建/获取会话状态
async function createMeeting(type: any) {
  const session = useSessionStore()
  if (type === 'init') {
    session.updateHistoryPaging({
      current: 1,
      pageSize: 10,
      total: 0,
    })
    // 加载历史消息
    await loadHistoryMessage().then((result: any) => {
      if (result && result.page === 1) {
        emitter.emit('scrollBottom')
      }
    })
    // 是否有留言消息
    const { data }: any = await requestHasLeaveMessage({
      keyId: session.visitorInformation.id,
      configId: session.configId,
      brand: session.brand || '',
      outCustId: session.visitorInformation.visitorId,
    })
    const { isLeave, ImMeeting, markUserinfo } = data
    if (isLeave === '1') {
      // 标记是否有留言消息  有留言需要加载并回复  不推送自助服务和猜你想问,不初始化会话及机器人
      session.updateUnReadMessageState(true)
      // 留言消息未读状态
      session.updateUnReadMessageState(false)
      session.updateMeetingId(ImMeeting.meetingId)
      session.updateSessionId(ImMeeting.sessionId)
      session.updateVisitor({
        id: markUserinfo.customerVisitContacts[0].contactWay,
        visitorId: markUserinfo.visitId,
        name: markUserinfo.visitName,
      })
      // 加载未读消息列表
      const result: any = await requestUnreadMessage({
        visitorId: markUserinfo.visitId,
        configId: session.configId,
      })
      console.log('result', result)
      if (result.code === 0 && result.data.length > 0) {
        renderUnreadMessage(result.data)
        // 更新未读消息状态
        await requestUpdateUnreadMessage({ visitorId: markUserinfo.visitId })
      }
    } else {
      // 没有留言消息 正常加载程序
      return new Promise(async (resolve) => {
        // 初始化渠道
        const result = await createSession()
        // 初始化会话
        await initSession(result.data, type)
        resolve(true)
      })
    }
  } else {
    return new Promise(async (resolve) => {
      // 初始化渠道
      const result = await createSession()
      // 初始化会话
      await initSession(result.data, type)
      resolve(true)
    })
  }
}
// 渲染未读(坐席回复的留言消息)
function renderUnreadMessage(messages) {
  const chat = useChatStore()
  messages.forEach((item) => {
    switch (item.type) {
      case '@imCloud_subject_leave_message@':
        chat.updateMessages({
          content: item.body,
          role: 'agent',
          type: 'text',
          id: item.mid,
          messageId: item.messageId,
        })
        break
    }
  })
}
// 创建会话
async function createSession() {
  const session = useSessionStore()
  return await requestCreate({
    keyId: session.visitorInformation.phone || session.visitorInformation.id, // 强认证渠道参数为用户手机号
    configId: session.configId,
    oldSessionId: session.sessionId,
    oldMeetingId: session.meetingId,
    outCustId: session.visitorInformation.id,
    visitorUrl: location.href,
    visitorName: session.visitorInformation.name,
    channelToken: '',
    rs: '',
    beanId: '',
  })
}
// 机器人发送消息
function requestRobotMessage(resolve, value, callback) {
  const session = useSessionStore()
  const channel = useChannelStore()
  requestRobotChat({
    configId: session.configId,
    brand: session.brand || '',
    platform: session.platform || '',
    input: value,
    contentMsgType: 1,
    inputType: 1,
    meetingId: session.meetingId,
    sessionId: session.sessionId,
    tenantId: channel.SystemInfo.tenantId,
    visitorId: session.visitor.visitorId,
    customerName: session.visitor.name,
    loginName: session.visitor.name,
  }).then(async (result: any) => {
    if (result.code === 0) {
      stop()
      start()
      callback && callback()
      // 每次机器人消息发送成功后要把销毁机器人定时器给重置了
      const { answerSource } = result.data
      switch (answerSource) {
        case 'NO_ANSWER':
          // 拒识
          await robotReject(result.data)
          break
        case 'KnowledgeBase':
          // 知识库
          robotKnowledge(result.data)
          break
        case 'KNOWLEDGE':
          // 知识库
          robotKnowledge(result.data)
          break
      }
      resolve(true)
    }
  })
}
// 拒识业务处理
async function robotReject(data: any) {
  const { rejectionTimes, robotIcsMessageId } = data
  const chat = useChatStore()
  const channel = useChannelStore()
  if (rejectionTimes >= channel.SystemInfo.robotRefuse) {
    // 拒识次数达到阈值，自动转人工
    console.log('自动转人工')
    await handlePreAgent('init')
  } else {
    // 拒识次数未达到阈值，继续拒识,且更新消息列表
    chat.updateMessages({
      content: data.title,
      role: 'robot',
      type: 'text',
      id: robotIcsMessageId,
    })
  }
}
// 知识库业务处理
function robotKnowledge(data) {
  const chat = useChatStore()
  const { robotIcsMessageId, msgType } = data
  switch (msgType) {
    case 'Recommend':
      chat.updateMessages({
        content: data.title,
        knowledgeList: data.chatRobotVOs,
        role: 'robot',
        type: 'Recommend',
        id: robotIcsMessageId,
      })
      break
    case 'Knowledge':
      chat.updateMessages({
        content: data.title,
        role: 'robot',
        type: 'html',
        id: robotIcsMessageId,
      })
      break
    default:
      chat.updateMessages({
        content: data.title,
        role: 'robot',
        type: 'text',
        id: robotIcsMessageId,
      })
      break
  }
}

// 预转人工前的业务处理
async function handlePreAgent(connectType: string) {
  const session = useSessionStore()
  const channel = useChannelStore()
  // 坐席是否开启转人工
  if (channel.SystemInfo.turnLaborAction) {
    // 黑名单拦截
    if (session.blackList === 'black') {
      showToast('人工繁忙,请稍后再试')
    } else {
      // 转人工
      // 1、机器人状态是否处于销毁状态
      if (
        session.robotState === robotState.DESTROY ||
        session.FAction === FAction.CANCEL_QUEUE
      ) {
        // 创建会话
        await createMeeting('reload')
      }
      await handleAgent(connectType)
    }
  } else {
    // 坐席未开启转人工
    showToast('渠道暂未开启转人工')
  }
}
// 转人工
async function handleAgent(connectType: string) {
  const session = useSessionStore()
  const chat = useChatStore()
  // 清除销毁机器人定时器
  if (session.robotState === robotState.OPEN) stop()
  // 每次会话都要初始化评价状态
  session.updateAgentEvaluateState(evaluateState.uncompleted)
  const channel = useChannelStore()
  // TODO 未读消息处理
  // 坐席是否在工作时间
  const result: any = await requestWorkTime({
    configId: session.configId,
    tenantId: channel.SystemInfo.tenantId,
  })
  if (result.code === 0) {
    // 获取websocket连接地址
    const { data: websocketUrl } = await requestWebsocketBaseUrl({
      sessionId: session.sessionId,
    })
    const params = {
      clientId: session.clientId,
      sessionId: session.sessionId,
      participantId: session.visitorInformation.visitorId,
      tenantId: channel.SystemInfo.tenantId,
      meetingId: session.meetingId,
      loginType: 'pc',
      retry: connectType === 'retry' ? 1 : 0,
    }
    // 将params和websocketUrl拼接成查询字符串
    const queryString = Object.keys(params)
      .map(
        (key) =>
          `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`,
      )
      .join('&')
    const fullUrl = `${websocketUrl}?${queryString}`
    session.updateWebsocketUrl(fullUrl)
    // 获取转接菜单
    const response: any = await requestTransferMenu({
      configId: session.configId,
      tenantId: channel.SystemInfo.tenantId,
    })
    const [transferMenu] = response.data
    session.updateTransferMenu(transferMenu)
    // TODO 转人工
    showLoadingToast({
      message: '连接坐席中',
      forbidClick: true,
      duration: 0,
      loadingType: 'spinner',
    })
    socketServer.connect(transferMenu, connectType)
  } else {
    // 坐席不在工作时间
    // 客户留言
    chat.updateMessages({
      role: 'system',
      type: 'leave',
      state: 'NO_WORKER_TIME',
      content: '坐席不在工作时间',
      id: uuidv7(),
    })
    // showToast('坐席不在工作时间')
  }
}
function loadHistoryMessage() {
  return new Promise(async (resolve) => {
    const session = useSessionStore()
    const result: any = await requestHistoryMessage({
      current: session.historyPaging.current,
      size: session.historyPaging.pageSize,
      visitorId: session.visitorInformation.visitorId,
      configId: session.configId,
    })
    if (result.code === 0 && result.data) {
      const { data, count }: any = result
      const messages = data.reverse()
      const historyMessage = handleHistoryMessage(messages)
      resolve({
        messages: historyMessage,
        page: session.historyPaging.current,
      })
      if (result.data.length >= session.historyPaging.pageSize) {
        session.updateHistoryPaging({
          current: ++session.historyPaging.current,
          pageSize: session.historyPaging.pageSize,
          total: count,
          more: true,
        })
      } else {
        session.updateHistoryPaging({
          current: ++session.historyPaging.current,
          pageSize: session.historyPaging.pageSize,
          total: count,
          more: false,
        })
      }
    } else {
      resolve(false)
    }
  })
}
export function handleHistoryMessage(list: any) {
  const chat = useChatStore()
  const session = useSessionStore()
  let historyMessage: any[] = []
  if (list.length === 0) return []
  list.forEach((item: any) => {
    const { type, body, messageId, mid, role } = item
    switch (role) {
      case 'visitor':
        historyMessage.push({
          content: body,
          role: 'visitor',
          type: type,
          id: mid,
          messageId,
        })
        break
      case 'robot':
        if (item.icsContentList && item.icsContentList.length) {
          // 历史消息知识推荐
          const knowledgeList = item.icsContentList.map((prop: any) => {
            return {
              knowledgeId: prop.id,
              knowledgeTitle: prop.content,
            }
          })
          historyMessage.push({
            content: body,
            knowledgeList: knowledgeList,
            role: 'robot',
            type: 'Recommend',
            id: mid,
            messageId,
          })
        } else {
          historyMessage.push({
            content: body,
            role: 'robot',
            type: 'html',
            id: mid,
            messageId,
          })
        }
        break
      case 'seat':
        if (item.type === '@imCloud_subject_message_user@') {
          historyMessage.push({
            content: body,
            role: 'seat',
            type: type,
            id: mid,
            messageId,
          })
        }
        break
    }
  })
  if (session.historyPaging.current === 1) {
    historyMessage.push({
      content: '以上是历史消息',
      role: 'system',
      type: 'text',
      id: uuidv7(),
      messageId: uuidv7(),
    })
  }
  chat.updateHistoryMessage(historyMessage)
  return historyMessage
}

// 客户留言
async function visitorLeave(type: string, value: any) {
  const session = useSessionStore()
  let params = {
    configId: session.configId,
    content: value,
    customerId: session.visitorInformation.id,
    htmlContent: `<div class="text-area-text">${value}</div>>`,
    meetingId: session.meetingId,
    skillId: session.transferMenu.masterSkillId,
    visitorId: session.visitorInformation.visitorId,
    sessionId: session.sessionId,
    msgScene: session.leaveType,
  }
  if (type === 'leaveMesgReply') {
    params['type'] = '@imCloud_subject_visitor_reply_leave_message@'
  }
  return await requestVisitorLeaveMessage(params)
}
export {
  createMeeting,
  createSession,
  handleInitState,
  handlePreAgent,
  handleSelfService,
  loadHistoryMessage,
  loadRobot,
  loadWelcome,
  sendRobotMessage,
  visitorLeave,
}
export default initSession
